package org.noahsark.utilities.common;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * Copy property values from the origin bean to the destination bean for all cases where 
 * the property names are the same.
 * <strong >modified from org.apache.commons.beanutils.BeanUtils.copyProperties(Object dest, Object orig) 
 * </strong>
 * 
 */
public class SimpleBeanCopyUtil {
	protected final Log log = LogFactory.getLog(getClass());

    /** default constructor. **/
    private SimpleBeanCopyUtil() {
    }

    /**
     * copy the properties of non-List.
     * copy the properties of orig object to the properties of dest object
     * 
     * @param dest object
     * @param orig object IllegalAccessException, InvocationTargetException
     */
    public static void copyProperties(Object dest, Object orig) {
        if (dest == null) {
            throw new IllegalArgumentException("No destination bean specified");
        }
        if (orig == null) {
            throw new IllegalArgumentException("No origin bean specified");
        }
//        if (LOGGER.isDebugEnabled()) {
//            LOGGER.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");
//        }

        // Copy the properties, converting as necessary
        if (orig instanceof DynaBean || orig instanceof Map || orig instanceof Collection) {
//            LOGGER.info(" SimpleBeanCopyUtil don't support the copies "
//                    + "for the reference Object or Collection .");
        } else /* if (orig is a standard JavaBean) */{
            PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(orig);
            for (int i = 0; i < origDescriptors.length; i++) {
                String name = origDescriptors[i].getName();

                Method readMethod = origDescriptors[i].getReadMethod();
                Method writeMethod = origDescriptors[i].getWriteMethod();

                if ("class".equals(name)) {
                    continue; // No point in trying to set an object's class
                }
                if (writeMethod != null && readMethod != null
                        && Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                    Object value = null;
                    try {
                        value = readMethod.invoke(orig);
                        if (value instanceof List) {
                            continue;
                        } else if (value instanceof java.util.Date) {
                            if (value != null) {
                                value = ((java.util.Date) value).clone();
                            }
                            PropertyUtils.setSimpleProperty(dest, name, value);
                            BeanUtils.copyProperty(dest, name, value);
                        } else {
                            writeMethod.invoke(dest, value);
//                            PropertyUtils.setSimpleProperty(dest, name, value);
//                            BeanUtils.copyProperty(dest, name, value);
                        }
                    } catch (Exception e) {
//                        LOGGER.debug("Method read error.", e);
                        continue;
                    }
                }
            }
        }
    }
}